package com.slipper.mybatis;

import jakarta.annotation.Resource;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Signature;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Map;
import java.util.Properties;

import static com.slipper.mybatis.Trigger.*;

@Component
@Intercepts({@Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class})})
public class UpdateInterceptor implements Interceptor {
    @Resource
    private List<Trigger> triggerList;

    @Override
    @SuppressWarnings("unchecked")
    public Object intercept(Invocation invocation) throws Throwable {
        MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];
        Object parameter = invocation.getArgs()[1];

        if (TriggerHelper.isTrigger()
                && parameter instanceof Map
                && ((Map<String, Object>) parameter).containsKey("sql")) {
            switch (mappedStatement.getSqlCommandType()) {
                case INSERT -> triggerList.forEach(item -> item.trigger(BEFORE_INSERT, (Map<String, Object>) parameter));
                case UPDATE -> triggerList.forEach(item -> item.trigger(BEFORE_UPDATE, (Map<String, Object>) parameter));
                case DELETE -> triggerList.forEach(item -> item.trigger(BEFORE_DELETE, (Map<String, Object>) parameter));
            }
        }

        // 执行 update 操作
        Object result = invocation.proceed();

        if (TriggerHelper.isTrigger()
                && parameter instanceof Map
                && ((Map<String, Object>) parameter).containsKey("sql")) {
            switch (mappedStatement.getSqlCommandType()) {
                case INSERT -> triggerList.forEach(item -> item.trigger(AFTER_INSERT, (Map<String, Object>) parameter));
                case UPDATE -> triggerList.forEach(item -> item.trigger(AFTER_UPDATE, (Map<String, Object>) parameter));
                case DELETE -> triggerList.forEach(item -> item.trigger(AFTER_DELETE, (Map<String, Object>) parameter));
            }
        }
        return result;
    }

    @Override
    public Object plugin(Object target) {
        return Interceptor.super.plugin(target);
    }

    @Override
    public void setProperties(Properties properties) {
        Interceptor.super.setProperties(properties);
    }
}
